package com.zzgc.modules.async;

import com.zzgc.common.entity.*;
import com.zzgc.common.response.Result;
import com.zzgc.common.utils.StringUtils;
import com.zzgc.modules.controller.BaseController;
import com.zzgc.modules.param.AuthUserParam;
import com.zzgc.modules.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * @Author:
 * @CreateTime: 2023-05-10  17:19
 * @Description:
 * @Version: 1.0
 */
@Component
@EnableAsync
public class AsyncStatistical {
    @Autowired
    SchoolPlanService schoolPlanService;
    @Autowired
    StudentArchivesService archivesService;
    @Autowired
    SchoolService schoolService;
    @Autowired
    AuthDepartService departService;
    @Autowired
    StaticDistrictVisualizationService districtVisualizationService;
    @Autowired
    StaticCityVisualizationService cityVisualizationService;
    @Autowired
    StaticProvincialVisualizationService provincialVisualizationService;

    /**
     *  更新学校总人数（异步）
     * @Author
     * @Description
     * @Date  2023/5/11 15:00
     * @Param
     * @return
     */
    @Async
    @Transactional
    public Future<List<SchoolPlan>> updateStudentNum(Long schoolId, String year) {
        // 判断正在进行的是第几次筛查
        int number = getNumber();
        // 查询学校的学生数量
        List<SchoolPlan> schoolPlans = new ArrayList<>();
        SchoolPlan schoolPlan = new SchoolPlan();
        schoolPlan.setSSchoolId(schoolId);
        schoolPlan.setSYear(year);
        schoolPlans = schoolPlanService.selectStudentNumber(schoolPlan);
        // 添加学校总数
        School school = new School();
        school.setId(schoolId);
        school.setSStudentNum(schoolPlans.get(schoolPlans.size() - 1).getSStudentNum()); // 添加学校管理人数
        schoolService.update(school); // 更新学校人数
        // 查询筛查计划表里是否存在记录 查询值学校ID、筛查次数、年份、市级编码、区县编码
        for (SchoolPlan plan : schoolPlans) {
            schoolPlan.setSSchoolId(plan.getSSchoolId());
            schoolPlan.setSYear(plan.getSYear());
            schoolPlan.setSParentCode(plan.getSParentCode());
            schoolPlan.setSAreaCode(plan.getSAreaCode());
            List<SchoolPlan> schoolPlans1 = schoolPlanService.queryByPage(schoolPlan);
            // 如果没有4条数据说明不完整
            if (schoolPlans1.size() != 4) { // 删除从新添加
                for (SchoolPlan schoolPlan1 : schoolPlans1) {
                    schoolPlanService.deleteById(schoolPlan1.getId());
                }
                StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[1];
                System.out.println("删除成功！(" + stackTrace.getClassName()+ ".java:" + stackTrace.getLineNumber() + ")");
            }else { // 有四条就修改，判断筛查到第几次了
                for (SchoolPlan schoolPlan1 : schoolPlans1) {
                    schoolPlan1.setSUpdateDate(new Date());
                    if (schoolPlan1.getSNumber() == number) {
                        schoolPlan1.setSState("进行中");
                    }else if (schoolPlan1.getSNumber() > number) {
                        schoolPlan1.setSState("未进行");
                    }else {
                        schoolPlan1.setSState("已结束");
                    }
                    schoolPlan1.setSStudentNum(plan.getSStudentNum());
                    schoolPlanService.update(schoolPlan1);
                }
                StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[1];
                System.out.println("修改成功！(" + stackTrace.getClassName()+ ".java:" + stackTrace.getLineNumber() + ")");
            }
            if (schoolPlans1.size() == 0) { // 直接添加
                for (int i = 1; i <= 4; i++) { // 添加4条
                    plan.setSNumber(i);
                    plan.setSState("未进行");
                    plan.setSCreateDate(new Date());
                    schoolPlanService.insert(plan);
                }
                StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[1];
                System.out.println("添加成功！(" + stackTrace.getClassName()+ ".java:" + stackTrace.getLineNumber() + ")");
            }
        }
        return new AsyncResult<>(schoolPlans);
    }

    /**
     *  更新学校筛查人数（异步）
     * @Author
     * @Description
     * @Date  2023/5/11 15:00
     * @Param
     * @return
     */
    @Async
    @Transactional
    public Future<Map> updateStudentScreenNum(Map<String, StudentArchives> map) {
        for (Map.Entry<String, StudentArchives> entry : map.entrySet()) {
            StudentArchives archives = entry.getValue();
            StudentArchives archives1 = new StudentArchives();
            archives1.setSSchoolName(archives.getSSchoolName());
            archives1.setSYear(archives.getSYear());
            archives1.setSNumber(archives.getSNumber());
            archives1.setTableName(archives.getTableName());
            Long count = archivesService.count(archives1);
            // 判断是否存在该学校
            School school = schoolService.queryByName(archives.getSSchoolName());
            if (StringUtils.isNull(school)){
                continue;
            }
            SchoolPlan schoolPlan = new SchoolPlan();
            schoolPlan.setSSchoolId(school.getId());
            schoolPlan.setSYear(archives.getSYear());
            schoolPlan.setSNumber(archives.getSNumber());
            // 查询出来一条记录，哪个学校，哪一年，第几次筛查
            List<SchoolPlan> schoolPlans1 = schoolPlanService.queryByPage(schoolPlan);
            if (schoolPlans1.size() == 1) {
                SchoolPlan schoolPlan1 = schoolPlans1.get(0);
                schoolPlan1.setSScreenNum(count.intValue());
                schoolPlanService.update(schoolPlan1);// 添加某一次的筛查记录
            }else {
                StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[1];
                System.out.println("查询筛查计划异常，不存在记录或存在多个记录(" + stackTrace.getClassName()+ ".java:" + stackTrace.getLineNumber() + ")");
            }
        }
        return new AsyncResult<>(map);
    }

    /**
     *  更新市级可视化数据
     * @Author
     * @Description
     * @Date  2023/5/19 10:10
     * @Param
     * @return
     */
    @Async
    public void updateCityAnalysis(){
        // 查询所有区县数据
        List<StaticDistrictVisualization> visualizations = districtVisualizationService.queryCountSum();
        for (StaticDistrictVisualization visualization : visualizations) {
            // 查询是否存在市级数据
            StaticCityVisualization cityVisualization = new StaticCityVisualization();
            cityVisualization.setYear(visualization.getYear());
            cityVisualization.setNumber(visualization.getNumber());
            cityVisualization.setCity(visualization.getCity());
            List<StaticCityVisualization> cityVisualizations = cityVisualizationService.queryByPage(cityVisualization);
            if (StringUtils.isNotEmpty(cityVisualizations)) { // 如果有数据则更新
                StaticCityVisualization average = getAverage(visualization);
                average.setId(cityVisualizations.get(0).getId());
                average.setUpdateTime(new Date());
                cityVisualizationService.update(average);
            }else {
                StaticCityVisualization average = getAverage(visualization);
                average.setCreateTime(new Date());
                cityVisualizationService.insert(average);
            }
        }
        // 计算省级占比
        updateProvincialAnalysis();
    }

    /**
     * 区县实体类转换市级实体类并计算占比
     * @ClassName AsyncStatistical
     * @Date 2023/5/26  15:00
     * @Version 1.0
     */
    private StaticCityVisualization getAverage(StaticDistrictVisualization district){
        StaticCityVisualization cityParam = new StaticCityVisualization();
        cityParam.setYear(district.getYear());
        cityParam.setNumber(district.getNumber());
        cityParam.setCity(district.getCity());
        cityParam.setCityName(cityParam.getCity() + "教育局");
        cityParam.setCount(district.getCount());
        cityParam.setInspect(district.getInspect());
        cityParam.setCoverage(keepDecimals(1,  district.getInspect() / (float)district.getCount())); // 视力覆盖率 = 检查人数 /  总人数
        cityParam.setAbnormalVision(district.getAbnormalVision());
        cityParam.setUnhealthy(keepDecimals(1,  district.getAbnormalVision() / (float)district.getInspect())); // 视力不良率 = 异常视力 / 检查人数
        cityParam.setMyopia(district.getMyopia());
        cityParam.setMyopiaRate(keepDecimals(1,  district.getMyopia() /(float)district.getInspect())); // 近视率 = 近视人数 / 检查人数
        cityParam.setManCount(district.getManCount());
        cityParam.setManMyopiaNum(district.getManMyopiaNum());
        cityParam.setManMyopiaRate(keepDecimals(1,  district.getManMyopiaNum() / (float)district.getManCount())); // 男生视力近视率 = 男生近视人数 / 男生检查人数
        cityParam.setWomanCount(district.getWomanCount());
        cityParam.setWomanMyopiaNum(district.getWomanMyopiaNum());
        cityParam.setWomanMyopiaRate(keepDecimals(1,  district.getWomanMyopiaNum() / (float)district.getWomanCount())); // 女生视力近视率 = 女生近视人数 / 女生检查人数
        return cityParam;
    }

    /**
     *  计算省级占比
     * @Author
     * @Description
     * @Date  2023/5/19 14:15
     * @Param
     * @return
     */
    private void updateProvincialAnalysis() {
        // 查询所有市数据
        List<StaticCityVisualization> staticCityVisualizations = cityVisualizationService.queryCountSum();
        for (StaticCityVisualization city : staticCityVisualizations) {
            StaticProvincialVisualization visualization = new StaticProvincialVisualization();
            visualization.setYear(city.getYear());
            visualization.setNumber(city.getNumber());
            List<StaticProvincialVisualization> provincial = provincialVisualizationService.queryByPage(visualization);
            // 判断是否存在省数据
            if (StringUtils.isNotEmpty(provincial)) { // 更新数据
                StaticProvincialVisualization average = getAverage(city);
                average.setId(provincial.get(0).getId());
                average.setUpdateTime(new Date());
                provincialVisualizationService.update(average);
            }else {
                StaticProvincialVisualization average = getAverage(city);
                average.setCreateTime(new Date());
                provincialVisualizationService.insert(average);
            }
        }
    }

    /**
     *  区县实体类转换市级实体类并计算占比
     * @ClassName AsyncStatistical
     * @Date 2023/5/26  14:59
     * @Version 1.0
     */
    private StaticProvincialVisualization getAverage(StaticCityVisualization city){
        StaticProvincialVisualization provincial = new StaticProvincialVisualization();
        provincial.setYear(city.getYear());
        provincial.setNumber(city.getNumber());
        provincial.setName("河南省教育局");
        provincial.setCount(city.getCount());
        provincial.setInspect(city.getInspect());
        provincial.setCoverage(keepDecimals(1,  city.getInspect() / (float)city.getCount())); // 视力覆盖率 = 检查人数 /  总人数
        provincial.setAbnormalVision(city.getAbnormalVision());
        provincial.setUnhealthy(keepDecimals(1,  city.getAbnormalVision() / (float)city.getInspect())); // 视力不良率 = 异常视力 / 检查人数
        provincial.setMyopia(city.getMyopia());
        provincial.setMyopiaRate(keepDecimals(1,  city.getMyopia() /(float)city.getInspect())); // 近视率 = 近视人数 / 检查人数
        provincial.setManCount(city.getManCount());
        provincial.setManMyopiaNum(city.getManMyopiaNum());
        provincial.setManMyopiaRate(keepDecimals(1,  city.getManMyopiaNum() / (float)city.getManCount())); // 男生视力近视率 = 男生近视人数 / 男生检查人数
        provincial.setWomanCount(city.getWomanCount());
        provincial.setWomanMyopiaNum(city.getWomanMyopiaNum());
        provincial.setWomanMyopiaRate(keepDecimals(1,  city.getWomanMyopiaNum() / (float)city.getWomanCount())); // 女生视力近视率 = 女生近视人数 / 女生检查人数
        return provincial;
    }

    public String keepDecimals(Integer digit, float number) {
        if (Float.isNaN(number)) {
            return "0.0";
        }
        return String.format("%." + digit + "f", number * 100);
    }

    /**
     *  根据时间段分配测试次数
     */
    private int getNumber() {
        int month = LocalDate.now().getMonth().getValue();
        switch (month){
            case 7: ;
            case 8: ;
            case 9: return 1;
            case 10: ;
            case 11: ;
            case 12: return 2;
            case 1: ;
            case 2: ;
            case 3: return 3;
            case 4: ;
            case 5: ;
            case 6: return 4;
        }
        return 0;
    }


}
